
#include <iostream>
#include <string.h>
#include <unordered_set>
#include "random.hpp"
#include <stdlib.h>
#include <cmath>
#define use_reservoir_sample(size, num)           \
    {                                             \
        int64_t setsize = 21;                     \
        if (num > 5)                              \
        {                                         \
            double val = log(num * 3.0) / log(4); \
            setsize += pow(4, ceil(val));         \
        }                                         \
        (size < setsize);                         \
    }
using namespace std;

int64_t random_integer(int64_t min, int64_t max)
{
    return rand() % (max - min) + min;
}

void test_123()
{
    std::unordered_set<int64_t> uset;
    //给 uset 容器添加数据
    uset.emplace(1);
    uset.emplace(2);
    uset.emplace(3);
    //查看当前 uset 容器存储元素的个数
    cout << "uset size = " << uset.size() << endl;
    //遍历输出 uset 容器存储的所有元素
    for (auto iter = uset.begin(); iter != uset.end(); ++iter)
    {
        cout << *iter << endl;
    }
}

int64_t *set_sample(int64_t size, int64_t num)
{
    std::unordered_set<int64_t> uset;
    int64_t sampled = 0;
    int64_t rand_value = 0;
    int64_t *numbers = (int64_t *)malloc(sizeof(int64_t) * num);
    while (sampled < num)
    {
        rand_value = random_integer(0, size);
        // if (uset.find(rand_value) == uset.end())
        if (uset.count(rand_value) == 0)
        {
            uset.emplace(rand_value);
            numbers[sampled] = rand_value;
            sampled += 1;
        }
    }
    return numbers;
}

int64_t *reservoir_sample(int64_t size, int64_t num)
{
    int64_t *reservoir = (int64_t *)malloc(sizeof(int64_t) * num);
    for (int64_t i = 0; i < size; i++)
    {
        if (i < num)
        {
            reservoir[i] = i;
        }
        else
        {
            int64_t rand_val = random_integer(0, i + 1);
            if (rand_val < num)
            {
                reservoir[rand_val] = i;
            }
        }
    }
    return reservoir;
}

int64_t *sample_index(int64_t size, int64_t num)
{
    double setsize = 21;
    if (num > 5)
    {
        double val = log(num * 3.0) / log(4);
        setsize += pow(4, ceil(val));
    }

    if (size < setsize)
    {
        return reservoir_sample(size, num);
    }
    else
    {
        return set_sample(size, num);
    }
}